package com.xiaoyu.lanling.feature.videomatch.controller

import `in`.srain.cube.util.CheckUtil
import `in`.srain.cube.util.LocalDisplay
import `in`.srain.cube.util.NetworkStatusManager
import `in`.srain.cube.util.internal.AppCallback
import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.app.Service
import android.content.Context
import android.media.AudioManager
import android.media.MediaPlayer
import android.os.SystemClock
import android.os.Vibrator
import android.text.TextUtils
import android.view.View
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.FragmentActivity
import com.facebook.drawee.view.SimpleDraweeView
import com.facebook.imagepipeline.postprocessors.IterativeBoxBlurPostProcessor
import com.tbruyelle.rxpermissions2.RxPermissions
import com.xiaoyu.base.app.App
import com.xiaoyu.base.app.AppContext
import com.xiaoyu.base.app.GlobalUI
import com.xiaoyu.base.data.UserData
import com.xiaoyu.base.data.UserInfoDataProvider
import com.xiaoyu.base.model.User
import com.xiaoyu.base.utils.RxUtils
import com.xiaoyu.base.utils.extensions.setOnClickDebounceListener
import com.xiaoyu.base.utils.extensions.setViewTag
import com.xiaoyu.base.utils.time.CountDown
import com.xiaoyu.lanling.R
import com.xiaoyu.lanling.activity.base.BaseBottomSheetDialogFragment
import com.xiaoyu.lanling.common.Constant
import com.xiaoyu.lanling.data.NotificationData
import com.xiaoyu.lanling.feature.gift.ChatGiftBottomSheetDialog
import com.xiaoyu.lanling.feature.util.mixdata.MixDataUploader
import com.xiaoyu.lanling.feature.videocall.data.VideoCallData
import com.xiaoyu.lanling.feature.videocall.model.ActionMessageType
import com.xiaoyu.lanling.feature.videocall.model.MessageType
import com.xiaoyu.lanling.feature.videocall.model.SystemMessageType
import com.xiaoyu.lanling.feature.videocall.util.VideoCallNotificationUtils
import com.xiaoyu.lanling.feature.videomatch.VideoMatchEvaluateDialogFragment
import com.xiaoyu.lanling.feature.videomatch.data.VideoMatchData
import com.xiaoyu.lanling.feature.videomatch.log.VideoMatchLogger
import com.xiaoyu.lanling.feature.voicecall.model.HangupReason
import com.xiaoyu.lanling.media.image.ImageViewUtil
import com.xiaoyu.lanling.media.image.UserImageLoadParam
import com.xiaoyu.lanling.router.Router
import com.xiaoyu.lanling.util.TextViewUtil
import com.xiaoyu.lib_av.datamodel.*
import com.xiaoyu.lib_av.datamodel.CallHangUpType.NEGATIVE
import com.xiaoyu.lib_av.datamodel.CallHangUpType.POSITIVE
import com.xiaoyu.lib_av.listener.AbstractVideoCallLifecycleListener
import com.xiaoyu.lib_av.manager.CallManager
import com.xiaoyu.net.util.NetUtils
import io.reactivex.Completable
import io.reactivex.Flowable
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.subjects.PublishSubject
import kotlinx.android.synthetic.main.video_match_activity.*
import java.util.*
import java.util.concurrent.TimeUnit

class VideoMatchCallViewController(val mFragmentActivity: FragmentActivity) : AbstractVideoCallLifecycleListener(), BaseBottomSheetDialogFragment.OnDestroyListener {

    companion object{
        const val CHARGE_START_DURATION = 10
    }

    private val onAudioFocusChangeListener = AudioManager.OnAudioFocusChangeListener { }

    private var mMainTaskTopActivity: Activity? = null
    private var mVoiceNetworkStatus: TextView? = null

    private var mRingtoneMediaPlayer: MediaPlayer? = null
    private var mVibrator: Vibrator? = null

    private val mIsCaller: Boolean
    private val mCallParams: CallParams?
    private val mFuid: String?
    private val mFromType: String?
    private var mCallDurationInS: Long = 0
    private var mWifiOffPublishSubject: PublishSubject<Boolean>? = null
    private var mVibratorDisposable: Disposable? = null
    private val mNotificationDisposable: Disposable? = null
    private var mDisplayUserDisposable: Disposable? = null
    private var mWifiDisposable: Disposable? = null
    private var mCountDownDisposable: Disposable? = null
    private var mIsHeadset = false
    private var mDisableVideoStartTime = 0L

    init {
        mIsCaller = mFragmentActivity.intent.getBooleanExtra(Constant.IntentKey.KEY_CHAT_CALL_IS_CALLER, false)
        mCallParams = mFragmentActivity.intent.getSerializableExtra(Constant.IntentKey.KEY_CHAT_CALL_CALL_PARAM) as? CallParams
        mFuid = mCallParams?.getFuid(UserData.getInstance().isSelf(mCallParams.fromUser.uid))
        mFromType = mFragmentActivity.intent.getStringExtra(Constant.PARAM_FROM)
        if (mFuid == null) {
            mFragmentActivity.finishAndRemoveTask()
        } else {
            CallManager.instance.create(this)
            initView()
            initBind()
            initBaseSupport()
            initPermissions()
            initHeadset()
        }
    }

    fun onResume() {
        mMainTaskTopActivity = App.getInstance().topActivity
        dismissNotification()
    }

    fun onStop() {
        if (!TextUtils.isEmpty(mFuid) && isCalling) {
            showNotification()
        }
    }

    fun onDestroy() {
        RxUtils.disposable(mNotificationDisposable, mDisplayUserDisposable, mWifiDisposable, mCountDownDisposable)
        closeRingtoneVibrator()
        stopTime()
        mWifiOffPublishSubject?.onComplete()
        dismissNotification()
        CallManager.instance.destroy()
    }

    private fun initView() {
        mVoiceNetworkStatus = mFragmentActivity.findViewById(R.id.voice_network_status)

        mFragmentActivity.remote_video_container.layoutParams.width = LocalDisplay.SCREEN_WIDTH_PIXELS
        mFragmentActivity.remote_video_container.layoutParams.height = LocalDisplay.SCREEN_HEIGHT_PIXELS
    }

    private fun initBind() {
        mFragmentActivity.voice_calling_gift?.setOnClickDebounceListener {
            val user = UserInfoDataProvider.getInstance().fetchFromMemory(mFuid)
            if (user.isNobody) {
                return@setOnClickDebounceListener
            }
            ChatGiftBottomSheetDialog.show(mFragmentActivity.supportFragmentManager, user, Constant.From.VIDEO_MATCH)
        }
        mFragmentActivity.voice_calling_switch_camera?.setOnClickDebounceListener {
            CallManager.instance.switchCamera()
        }
        mFragmentActivity.voice_calling_hangup?.setOnClickDebounceListener {
            if (TextUtils.isEmpty(mFuid)) {
                return@setOnClickDebounceListener
            }
            showHangupConfirmDialog()
        }
        mFragmentActivity.voice_call_hangup?.setOnClickDebounceListener {
            if (TextUtils.isEmpty(mFuid)) {
                return@setOnClickDebounceListener
            }
            showHangupConfirmDialog()
        }
        mFragmentActivity.voice_receive_hangup?.setOnClickDebounceListener {
            sendCallMessage()
            rejectAndFinish()
        }
        mFragmentActivity.voice_receive_answer?.setOnClickDebounceListener {
            receive()
        }
        mFragmentActivity.charge_button.setOnClickDebounceListener {
            Router.instance.gotoCoinProductListAndBalanceActivity(mFragmentActivity)
            mFragmentActivity.charge_layout.visibility = View.GONE
            mCountDownDisposable?.dispose()
        }
        mFragmentActivity.voice_call_camera_switch.setOnClickDebounceListener {
            val selected = !it.isSelected
            updateCameraSwitch(selected)
            CallManager.instance.enableLocalVideo(selected)
        }
        mFragmentActivity.voice_receive_camera_switch.setOnClickDebounceListener {
            val selected = !it.isSelected
            updateCameraSwitch(selected)
            CallManager.instance.enableLocalVideo(selected)
        }
        mFragmentActivity.local_video_container.setOnClickDebounceListener {
            val selected = !mFragmentActivity.voice_call_camera_switch.isSelected
            updateCameraSwitch(selected)
            CallManager.instance.enableLocalVideo(selected)
        }
    }

    @SuppressLint("CheckResult")
    private fun initBaseSupport() {
        mWifiOffPublishSubject = PublishSubject.create()
        mWifiOffPublishSubject?.let {
            mWifiDisposable = it
                    .throttleFirst(2000, TimeUnit.MILLISECONDS)
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe({ GlobalUI.getInstance().showToast("当前为非 wifi 网络, 不影响通话功能使用") }) { initBaseSupport() }
        }
        if (!NetworkStatusManager.getInstance().isWifi) {
            mWifiOffPublishSubject?.onNext(true)
        }
    }

    @SuppressLint("CheckResult")
    private fun initPermissions() {
        if (mFragmentActivity.isFinishing || mFragmentActivity.isDestroyed) {
            return
        }
        RxPermissions(mFragmentActivity)
                .request(Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                .subscribe({ granted: Boolean ->
                    if (granted) {
                        // checkNotificationPermission()
                        processData()
                    } else {
                        GlobalUI.getInstance().showToast("请检查权限是否开启")
                        finish()
                    }
                }) { obj: Throwable -> obj.printStackTrace() }
    }

    private fun initHeadset() {
        val audioManager = AppContext.getContext().getSystemService(Context.AUDIO_SERVICE) as AudioManager
                ?: return
        audioManager.requestAudioFocus(onAudioFocusChangeListener, AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT)
        if (audioManager.isWiredHeadsetOn || audioManager.isBluetoothA2dpOn) {
            headsetOn()
        } else {
            headsetOff()
        }
    }

    private fun processData() {
        if (!NetUtils.isConnected(AppContext.getContext(), true)) {
            finish()
            return
        }
        if (TextUtils.isEmpty(mFuid)) {
            finish()
            return
        }
        showUserData(mFuid)
        setupLocalVideo()
        processStatus()
    }

    @SuppressLint("CheckResult")
    private fun showUserData(uid: String?) {
        mDisplayUserDisposable = Completable.fromAction { UserInfoDataProvider.getInstance().ensureUser(uid) }
                .compose(RxUtils.ioToMainCompletableScheduler<Any>())
                .subscribe {
                    val user: User = UserInfoDataProvider.getInstance().fetchFromMemory(uid)
                    ImageViewUtil.loadAvatarRoundWithBoard(mFragmentActivity.user_avatar, user, 96, 2, R.color.user_info_avatar_border, true)
                    mFragmentActivity.user_nickname?.setUser(user)
                }
    }

    private fun setupLocalVideo() {
        CallManager.instance.setupLocalVideo(mFragmentActivity.local_video_container)
        updateCameraSwitch(true)
    }

    private val isCalling: Boolean
        get() = CallManager.instance.isCalling

    private fun processStatus() {
        if (mIsCaller) {
            call()
            showCallStatus()
        } else {
            receive()
            showCallingStatus()
        }
    }

    private fun showCallStatus() {
        mFragmentActivity.voice_status?.text = mFragmentActivity.getString(R.string.video_call_inviting)
        mFragmentActivity.voice_call_layout?.visibility = View.VISIBLE
    }

    private fun showCallingStatus() {
        mFragmentActivity.user_info_group?.visibility = View.GONE
        mFragmentActivity.voice_call_layout?.visibility = View.GONE
        mFragmentActivity.voice_receive_layout?.visibility = View.GONE
        mFragmentActivity.voice_calling_layout?.visibility = View.VISIBLE
    }

    private fun showReceiveStatus() {
        mFragmentActivity.voice_status?.text = mFragmentActivity.getString(R.string.video_call_invited)
        mFragmentActivity.voice_receive_layout?.visibility = View.VISIBLE
    }

    private fun startTime() {
        mFragmentActivity.voice_calling_time?.let {
            it.base = SystemClock.elapsedRealtime()
            it.start()
        }
    }

    private fun stopTime() {
        mFragmentActivity.voice_calling_time?.stop()
    }

    private fun finish() {
        stopTime()
        mFragmentActivity.finishAndRemoveTask()
    }

    private fun sendCallMessage() {
        val hasConnect = mCallDurationInS > 0
        mFuid?.let {
            if (hasConnect) {
                val duration = mCallDurationInS.toInt()
                VideoCallData.sendVoiceStatusMessageForCall(it, duration.toLong(), mFromType ?: "")
            } else {
                if (mIsCaller) {
                    VideoCallData.sendVoiceStatusMessageForCancel(it)
                } else {
                    VideoCallData.sendVoiceStatusMessageForReject(it)
                }
            }
        }
    }

    private fun rejectAndFinish() {
        reject()
        finish()
    }

    private fun call() {
        mCallParams?.let {
            VideoMatchLogger.logVideoMatchCallStart()
            CallManager.instance.call(it, object : AppCallback<Boolean> {
                override fun onSuccess(t: Boolean) {
                    VideoMatchLogger.logVideoMatchCallSucceed()
                }

                override fun onError(e: Throwable) {
                    VideoMatchLogger.logVideoMatchCallFailed("sdk_error")
                    finish()
                }
            })
            playRingtone()
        }
    }

    private fun reject() {
        CallManager.instance.response(mFuid, CallResponseType.REFUSE)
    }

    private fun hangup(reason: String) {
        VideoMatchLogger.logVideoMatchCallRequestHangUp(mCallDurationInS, reason, CallHangUpType.POSITIVE)
        CallManager.instance.hangUp(mFuid, CallHangUpType.POSITIVE)
    }

    private fun receive() {
        CallManager.instance.response(mFuid, VideoCallData.ActionType.ACCEPT)
    }

    private fun playRingtone() {
        if (mRingtoneMediaPlayer != null && mRingtoneMediaPlayer?.isPlaying == true) {
            return
        }
        try {
            mRingtoneMediaPlayer = MediaPlayer.create(mFragmentActivity, R.raw.raw_chat_voice_ringtone)
            mRingtoneMediaPlayer?.isLooping = true
            mRingtoneMediaPlayer?.start()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    private fun closeRingtone() {
        mRingtoneMediaPlayer?.pause()
        mRingtoneMediaPlayer?.stop()
        mRingtoneMediaPlayer?.reset()
        mRingtoneMediaPlayer?.release()
        mRingtoneMediaPlayer?.setOnPreparedListener(null)
        mRingtoneMediaPlayer = null
    }

    private fun playVibratorLooping() {
        mVibratorDisposable = Flowable.interval(0, 6, TimeUnit.SECONDS)
                .onBackpressureDrop()
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({ aLong: Long? -> playVibrator() }) { obj: Throwable -> obj.printStackTrace() }
    }

    private fun playVibrator() {
        if (mVibrator == null) {
            mVibrator = mFragmentActivity.getSystemService(Service.VIBRATOR_SERVICE) as? Vibrator
        }
        mVibrator?.vibrate(2000)
    }

    private fun closeVibrator() {
        RxUtils.disposable(mVibratorDisposable)
        mVibrator?.cancel()
        mVibrator = null
    }

    private fun playRingtoneVibrator() {
        playRingtone()
        playVibratorLooping()
    }

    private fun closeRingtoneVibrator() {
        closeRingtone()
        closeVibrator()
    }

    private fun headsetOn() {
        if (mIsHeadset) {
            return
        }
        mIsHeadset = true
        CallManager.instance.isEnableSpeaker = false
    }

    private fun headsetOff() {
        if (!mIsHeadset) {
            return
        }
        mIsHeadset = false
        CallManager.instance.isEnableSpeaker = true
    }

    private fun showPoorNetworkStatus() {
        mVoiceNetworkStatus?.visibility = View.VISIBLE
    }

    private fun dismissPoorNetworkStatus() {
        mVoiceNetworkStatus?.visibility = View.GONE
    }

    private fun showNotification() {
        mCallParams?.let {
            VideoCallNotificationUtils.instance.showNotification(it, mIsCaller, false)
        }
    }

    private fun dismissNotification() {
        VideoCallNotificationUtils.instance.dismissNotification()
    }

    override fun onCallFailed(fuid: String, errorType: String) {
        when (errorType) {
            CallFailType.NO_RESPONSE -> GlobalUI.getInstance().showToast("对方暂不方便接听")
            CallFailType.ILLEGAL_ARGUMENT -> GlobalUI.getInstance().showToast("参数错误")
            CallFailType.NOT_LOGIN -> GlobalUI.getInstance().showToast("暂未连接上服务器，请稍后再试")
            CallFailType.UNKNOWN -> GlobalUI.getInstance().showToast("未知错误")
        }
        VideoMatchLogger.logVideoMatchCallFailed(errorType)
        hangup(HangupReason.UNKNOWN)
        finish()
    }

    override fun onRespondCall(fuid: String, responseType: String) {}
    override fun onCallResponded(fuid: String, responseType: String) {
        when (responseType) {
            CallResponseType.BUSY_LINE, CallResponseType.REFUSE -> {
                VideoMatchLogger.logVideoMatchCallFailed(responseType)
                GlobalUI.getInstance().showToast("对方暂不方便接听")
                hangup(HangupReason.UNKNOWN)
                finish()
            }
            CallResponseType.ACCEPT -> {
            }
        }
    }

    override fun onCancelCall(fuid: String) {
        VideoMatchLogger.logVideoMatchCallFailed("cancel")
        finish()
    }

    override fun onCallCanceled(callParams: CallParams) {
        finish()
    }

    override fun onCallConnecting(fuid: String) {}
    override fun onCallConnected(fuid: String) {
        startTime()
        showCallingStatus()
        closeRingtoneVibrator()
        connectedWithServer(fuid)
    }

    private fun connectedWithServer(fuid: String) {
        if (mIsCaller) {
            VideoMatchLogger.logVideoMatchCallConnected()
            VideoMatchData.establishConnection(fuid)
        }
    }

    override fun onCallDisconnected(fuid: String, @CallHangUpType.HangUpTypeDef hangUpType: String) {
        when (hangUpType) {
            NEGATIVE -> {
                VideoMatchLogger.logVideoMatchCallRequestHangUp(mCallDurationInS, HangupReason.OTHER_DISCONNECT, CallHangUpType.NEGATIVE)
                VideoMatchData.hangup(mFuid, HangupReason.UNKNOWN)
                showEvaluateDialogOrFinish()
            }
            POSITIVE -> {
                showEvaluateDialogOrFinish()
            }
            else -> finish()
        }
    }

    override fun onNetStatusReported(good: Boolean, uid: String) {
        if (good) {
            dismissPoorNetworkStatus()
        } else {
            showPoorNetworkStatus()
        }
    }

    override fun onAudioDeviceChanged(headset: Boolean) {
        if (headset) {
            headsetOn()
        } else {
            headsetOff()
        }
    }

    override fun onStatus(totalDurationInS: Long) {
        mCallDurationInS = totalDurationInS
    }

    override fun onMessageSend(message: CallMessage) {}

    override fun onMessageReceive(message: CallMessage) {
        when (message.getType()) {
            MessageType.ACTION -> onActionMessageReceive(message)
            MessageType.SYSTEM -> onSystemMessageReceive(message)
        }
    }

    override fun onRemoteVideoReceived(fuid: String) {
        CallManager.instance.setupRemoteVideo(mFragmentActivity.remote_video_container, fuid)
    }

    private fun onActionMessageReceive(message: CallMessage) {
        when (message.attrs?.optString("actionType")) {
            ActionMessageType.HANGUP -> {
                if (mIsCaller) {
                    sendCallMessage()
                }
                hangup(HangupReason.COIN_NOT_ENOUGH)
            }
        }
    }

    private fun onSystemMessageReceive(message: CallMessage) {
        when (message.attrs?.optString("subtype")) {
            SystemMessageType.EARNING_TIP -> {
                TextViewUtil.displayOrGone(mFragmentActivity.earning_tip, message.attrs?.optString("earningDesc"))
            }
            SystemMessageType.COIN_NOT_ENOUGH -> {
                val countDown = CountDown.createFromJson(message.attrs?.optJson("countDown"))
                mFragmentActivity.charge_layout.visibility = if (countDown.shouldDoUpdateByServers()) View.VISIBLE else View.GONE
                mCountDownDisposable?.dispose()
                mCountDownDisposable = Observable.interval(0, 1, TimeUnit.SECONDS)
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe {
                            if (!countDown.shouldDoUpdateByServers()) {
                                mCountDownDisposable?.dispose()
                                return@subscribe
                            }
                            mFragmentActivity.count_down_desc.text = mFragmentActivity.getString(R.string.call_coin_not_enough_count_down_desc, countDown.digitalCountDownTextByServers)
                        }
            }
        }
    }

    private fun checkNotificationPermission() {
        val notificationEnable: Boolean = CheckUtil.isNotificationChannelEnabled(mFragmentActivity, NotificationData.GroupId.CALL, NotificationData.ChannelId.CALL_VIDEO_MATCH)
        if (!notificationEnable) {
            showNotificationPermissionDialog()
        }
    }

    private fun showNotificationPermissionDialog() {
        AlertDialog.Builder(mFragmentActivity)
                .setMessage("请给予「电话」相关的通知权限，以保证 App 能够正常工作")
                .setPositiveButton("确定") { _, _ -> Router.instance.gotoNotificationSettings() }
                .show()
    }

    private fun loadBackground(avatar: SimpleDraweeView?, user: User) {
        avatar?.setViewTag(Constant.GlobalViewTagDefine.VIEW_TAG_FOR_USER, user)
        val thumbnailParam = UserImageLoadParam.newBuilder()
                .setUser(user, 56, 56) // same size with the avatar in R.layout.item_main_conversation
                .setPostProcessor(IterativeBoxBlurPostProcessor(2, 4))
                ?.setOverlayResId(R.drawable.chat_call_background_overlay_shape)
                ?.build()
        val param = UserImageLoadParam.newBuilder()
                .setUser(user, LocalDisplay.SCREEN_WIDTH_DP, LocalDisplay.SCREEN_HEIGHT_DP)
                .setPostProcessor(IterativeBoxBlurPostProcessor(2, 4))
                ?.setOverlayResId(R.drawable.chat_call_background_overlay_shape)
                ?.setLowResImageLoadParam(thumbnailParam)
                ?.build()
        ImageViewUtil.loadImage(avatar, param)
    }

    private fun updateCameraSwitch(selected: Boolean) {
        mFragmentActivity.voice_call_camera_switch.isSelected = selected
        mFragmentActivity.voice_receive_camera_switch.isSelected = selected
        mFragmentActivity.voice_receive_camera_switch.text = mFragmentActivity.getString(if (selected) R.string.video_call_camera_on else R.string.video_call_camera_off)
        mFragmentActivity.local_video_off_tip.visibility = if (selected) View.GONE else View.VISIBLE
    }

    private fun showHangupConfirmDialog() {
        AlertDialog.Builder(mFragmentActivity)
                .setMessage(R.string.video_call_hangup_confirm_dialog_message)
                .setPositiveButton(R.string.action_confirm) { dialog, which ->
                    sendCallMessage()
                    hangup(HangupReason.HANGUP)
                }
                .setNegativeButton(R.string.action_cancel) { _, _ -> }
                .show()
    }

    private fun showEvaluateDialogOrFinish() {
        val self: User = UserData.getInstance().user
        if (self.isMale && mCallDurationInS >= CHARGE_START_DURATION) {
            if (mFragmentActivity.isFinishing || mFragmentActivity.isDestroyed) {
                return
            }
            val user = UserInfoDataProvider.getInstance().ensureAndGetUser(mFuid)
            VideoMatchEvaluateDialogFragment.show(mFragmentActivity.supportFragmentManager, user, this)
        } else {
            finish()
        }
    }

    override fun onDialogDestroy() {
        finish()
    }

    override fun onRemoteVideoDisableStateChanged(fuid: String, disable: Boolean) {
        val user = UserInfoDataProvider.getInstance().ensureAndGetUser(fuid)
        mFragmentActivity.remote_video_off_tip.visibility = if (disable) View.VISIBLE else View.GONE
        updateVideoStatusForFemale(user, disable)
    }

    override fun onLocateVideoDisableStateChanged(disable: Boolean) {
        super.onLocateVideoDisableStateChanged(disable)
        val user = UserData.getInstance().user
        updateVideoStatusForFemale(user, disable)
        logEventForVideoDisable(disable)
    }

    private fun updateVideoStatusForFemale(user: User, disable: Boolean) {
        if (!user.isMale) {
            mFragmentActivity.video_status?.visibility = if (disable) View.VISIBLE else View.GONE
            mFragmentActivity.video_status?.text = if (user.isSelf) mFragmentActivity.getString(R.string.video_match_video_status_tip_female_disable_self) else mFragmentActivity.getString(R.string.video_match_video_status_tip_female_disable_other)
        }
    }

    override fun onLocalVideoFailure() {
        MixDataUploader.instance.submit(UUID.randomUUID().toString())
    }

    private fun logEventForVideoDisable(disable: Boolean) {
        if (disable) {
            mDisableVideoStartTime = System.currentTimeMillis()
            VideoMatchLogger.disableVideo()
        } else {
            val duration = (System.currentTimeMillis() - mDisableVideoStartTime) / 1000
            VideoMatchLogger.enableVideo(duration)
            mDisableVideoStartTime = 0
        }
    }
}